﻿using BLevy.Datos.Interfases;
using BLevy.Entidad;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using DapperExtensions;

namespace BLevy.Datos.Repositories
{
    public interface IAdherenteRepository : IRepository<Adherente>
    {
        IList<Adherente> FindByIdSocioActivos(int nroSocio);
        IList<Adherente> FindByIdSocioInactivos(int nroSocio);
        int AdherenteBaja(int adherente_id, AdherenteBaja baja);
        IList<Adherente> FindAllConSocioZona(int? localidad_id, int? zona_id, int? activo);

    }

    public class AdherenteRepository : IAdherenteRepository
    {

        protected readonly IDbConnection _db;

        public AdherenteRepository()
        {
            try
            {
                _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString());
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Adherente> FindAll()
        {
            string query = "SELECT * FROM ADHERENTES";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Adherente>(query).ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IQueryable<Adherente> Find(System.Linq.Expressions.Expression<Func<Adherente, bool>> predicate)
        {
            throw new NotImplementedException();
        }

        public Adherente FindById(int id)
        {
            string query = "SELECT * FROM ADHERENTES WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Adherente>(query, new { id = id }).SingleOrDefault();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public int Add(Adherente newEntity)
        {
            string query = "INSERT INTO ADHERENTES (SOCIO_ID, APELLIDO, NOMBRES, DOCUMENTO, FECHA_NACIMIENTO, " +
                                       "FECHA_INGRESO, VIGENCIA, EDAD, PARENTESCO, DIRECCION, LOCALIDAD_ID, ZONA_ID, TELEFONO, EMAIL, " +
                                       "ADICIONAL, PAMI, CONVENIO, OBSERVACIONES, ACTIVO) " +
                                       "VALUES (@socio_id, @apellido, @nombres, @documento, @fecha_nacimiento, @fecha_ingreso, " +
                                       "@vigencia, @edad, @parentesco, @direccion, @localidad_id, @zona_id, @telefono, @email, " +
                                       "@adicional, @pami, @convenio, @observaciones, @activo)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        socio_id = newEntity.socio_id,
                        apellido = newEntity.apellido,
                        nombres = newEntity.nombres,
                        documento = newEntity.documento,
                        fecha_nacimiento = newEntity.fecha_nacimiento,
                        fecha_ingreso = newEntity.fecha_ingreso,
                        vigencia = newEntity.vigencia,
                        edad = newEntity.edad,
                        parentesco = newEntity.parentesco,
                        direccion = newEntity.direccion,
                        localidad_id = newEntity.localidad.id,
                        zona_id = newEntity.zona.id,
                        telefono = newEntity.telefono,
                        email = newEntity.email,
                        adicional = newEntity.adicional,
                        pami = newEntity.pami,
                        convenio = newEntity.convenio,
                        observaciones = newEntity.observaciones,
                        activo = newEntity.activo
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Remove(int id)
        {
            string query = "UPDATE ADHERENTES SET ACTIVO = 0 " +
                "WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new { id = id });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public int Modify(Adherente entity)
        {
            string query = "UPDATE ADHERENTES SET SOCIO_ID = @socio_id, APELLIDO = @apellido, NOMBRES = @nombres, DOCUMENTO = @documento, FECHA_NACIMIENTO = @fecha_nacimiento, " +
                "FECHA_INGRESO = @fecha_ingreso, VIGENCIA = @vigencia, EDAD = @edad, PARENTESCO = @parentesco, DIRECCION = @direccion, LOCALIDAD_ID = @localidad_id, ZONA_ID = @zona_id, " +
                "TELEFONO = @telefono, EMAIL = @email, ADICIONAL = @adicional, PAMI = @pami, CONVENIO = @convenio, OBSERVACIONES = @observaciones, ACTIVO = @activo " +
                "WHERE ID = @id";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Execute(query, new
                    {
                        socio_id = entity.socio_id,
                        apellido = entity.apellido,
                        nombres = entity.nombres,
                        documento = entity.documento,
                        fecha_nacimiento = entity.fecha_nacimiento,
                        fecha_ingreso = entity.fecha_ingreso,
                        vigencia = entity.vigencia,
                        edad = entity.edad,
                        parentesco = entity.parentesco,
                        direccion = entity.direccion,
                        localidad_id = entity.localidad.id,
                        zona_id = entity.zona.id,
                        telefono = entity.telefono,
                        email = entity.email,
                        adicional = entity.adicional,
                        pami = entity.pami,
                        convenio = entity.convenio,
                        observaciones = entity.observaciones,
                        activo = entity.activo,
                        id = entity.id
                    });
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Adherente> FindByIdSocioActivos(int nroSocio)
        {
            string query = "SELECT * FROM ADHERENTES " +
                           "INNER JOIN LOCALIDADES ON LOCALIDADES.ID = ADHERENTES.LOCALIDAD_ID " +
                           "INNER JOIN ZONAS ON ZONAS.ID = ADHERENTES.ZONA_ID " +
                           "WHERE SOCIO_ID =" + nroSocio + " AND ADHERENTES.ACTIVO = 1";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Adherente, Localidad, Zona, Adherente>(query,
                        (adherente, localidad, zona) =>
                        {
                            adherente.localidad = localidad;
                            adherente.zona = zona;
                            return adherente;
                        }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }

        public IList<Adherente> FindByIdSocioInactivos(int nroSocio)
        {
            string query = "select A.* FROM ADHERENTES A INNER JOIN ADHERENTESBAJAS B ON A.id = B.ADHERENTE_ID " +
                           "WHERE A.SOCIO_ID = @socio AND A.ACTIVO = 0 AND a.id IN (SELECT X.ID FROM (SELECT MAX(ID) ID, ADHERENTE_ID FROM ADHERENTESBAJAS GROUP BY ADHERENTE_ID) X " +
                           "INNER JOIN ADHERENTESBAJAS B ON X.ID = B.ID WHERE OPERACION = 'B' AND TIPO_BAJA = 'A')";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    return _db.Query<Adherente>(query,
                        new
                        {
                            socio = nroSocio
                        }).ToList();
                }
            }
            catch (Exception e)
            {
                throw e;
            }
        }

        public int AdherenteBaja(int adherente_id, AdherenteBaja baja)
        {
            string query = "UPDATE ADHERENTES SET ACTIVO = 0 " +
                "WHERE ID = @id";

            string query_baja = "INSERT INTO ADHERENTESBAJAS (ADHERENTE_ID, FECHA, MOTIVO, OPERACION, TIPO_BAJA) " +
                "VALUES (@adherente_id, @fecha, @motivo, @operacion, @tipo_baja)";

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {
                    _db.Open();
                    IDbTransaction transaction = _db.BeginTransaction();

                    int filasAfectadas = _db.Execute(query, new { id = adherente_id }, transaction);

                    filasAfectadas += _db.Execute(query_baja, new
                    {
                        adherente_id = baja.adherente_id,
                        fecha = baja.fecha,
                        motivo = baja.motivo,
                        operacion = baja.operacion,
                        tipo_baja = baja.tipo_baja
                    }, transaction);

                    transaction.Commit();

                    return filasAfectadas;
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }


        public IList<Adherente> FindAllConSocioZona(int? localidad_id, int? zona_id, int? activo)
        {
            string query = "SELECT * FROM ADHERENTES " +
                "INNER JOIN SOCIOS ON SOCIOS.ID = ADHERENTES.SOCIO_ID " +
                "INNER JOIN ZONAS ON ZONAS.ID = SOCIOS.ZONA_ID " + 
                "WHERE ((SOCIOS.LOCALIDAD_ID = @localidad_id) or (@localidad_id IS NULL)) " + 
                "AND ((SOCIOS.ZONA_ID = @zona_id) OR (@zona_id IS NULL)) " +
                "AND ((SOCIOS.ACTIVO = @activo) OR (@activo IS NULL)) " ;

            try
            {
                using (IDbConnection _db = new MySqlConnection(ConfigurationManager.ConnectionStrings["LEVYDB"].ToString()))
                {

                    return _db.Query<Adherente, Socio, Zona, Adherente>(query, (adherente, socio, zona) =>
                    {
                        adherente.socio = socio;
                        adherente.socio.zona = zona;
                        return adherente;
                    }, new { localidad_id = localidad_id, zona_id = zona_id, activo = activo }, splitOn: "id").ToList();
                }
            }
            catch(Exception e)
            {
                throw e;
            }
        }
    }
}
